<?php
namespace Api\InterfaceApi;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\GetMapping;
use Hyperf\HttpServer\Annotation\PostMapping;
use Mine\MineApi;
use OpenAI;
use Psr\Container\ContainerExceptionInterface;
use OpenAI\Client;
use Psr\Container\NotFoundExceptionInterface;

/**
 * 聊天
 */
#[Controller(prefix: "chat")]
class ChatController extends MineApi
{
    public string $openaiApiKey = '';
    public Client $openaiClient;

    /**
     * 上下文的长度
     * @var int
     */
    public int $max_tokens = 2500;
    /**
     * 输入内容的长度
     * @var int
     */
    public int $max_input_len = 100;

    /**
     * @throws \Exception
     */
    public function __construct()
    {
        parent::__construct();
        $this->openaiApiKey = env('OPENAI_KEY','');
        if(empty($this->openaiApiKey)){
            throw new \Exception('请先配置OPENAI_KEY');
        }
        $this->openaiClient = OpenAI::client($this->openaiApiKey);
    }


    /**
     * 发送消息
     * @return \Psr\Http\Message\ResponseInterface
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    #[PostMapping('sendMessage')]
    public function sendMessage()
    {
        // 从请求中获取输入文本
        $input = $this->request->input('prompt','');
        //自己维护一个上下文参数。前端提交过来的，格式如下：[你]你会写代码吗[AI]会呀，我会写代码
        $context = $this->request->input('context','');
        //清理输入内容
        $input = trim($input);
        if(empty($input)){
            return $this->error('你在说什么？');
        }
        //记录日志 - 提问
        logger()->info(json_encode([
            'type'=>'提问',
            'ip'=>$this->request->ip(),
            'prompt'=>$input,
        ]));
        if(is_numeric($input)){
            return $this->success(['result'=>'你在说啥？']);
        }
        //上下文的长度限制
        if(strlen($context)>$this->max_tokens){
            $context = substr($context,-$this->max_tokens);
        }
        //输入的长度限制
        if(strlen($input)>$this->max_input_len){
            return $this->error("输入太长，不能超过{$this->max_input_len}个字符。中文算两个字符。");
        }

        // 提供输入文本和上下文并获取响应
        $response = $this->openaiClient->completions()->create([
            'model' => 'text-davinci-003',
            'prompt' => $context,//最终提交的对话
            'max_tokens' => $this->max_tokens,//是生成的文本最大长度
            'n' => 1,//是生成的文本数量
            'temperature' => 0.8,//温度
            'frequency_penalty'=>0,//值越高越啰嗦
            'presence_penalty'=>0,//值越高越啰嗦
        ]);
        //记录日志 - 回答
        logger()->info(json_encode([
            'type'=>'响应',
            'ip'=>$this->request->ip(),
            'response'=>$response,
        ]));
        $result = $response['choices'][0]['text'];
        if(empty($result)){
            $result = "当前使用人数太多";
        }
        //接口返回的值，会包含提交时的称呼[AI],截取掉。
        $result = trim(strrchr($result,'[AI]'),"[AI]")?:$result;
        $result = trim($result,"\n");
        // 输出响应
        return $this->success('',['result'=>$result]);
    }
    #[GetMapping('robot')]
    public function robot(){
        $data =[
            'desc'=>'对话配置',
            'id'=>2,
            'img'=>0,
            'key'=>'robot',
            'orderNum'=>1,
            'param1'=>'智能AI',
            'param2'=>'',
            'status'=>1,
            'title'=>'机器人设置',

        ];

        //记录日志 - 使用系统
        logger()->info(json_encode([
            'type'=>'进入系统',
            'ip'=>$this->request->ip(),
        ]));
        return $this->success($data);
    }
}
